package com.jccfc.common;

import com.alibaba.fastjson.JSON;
import com.jccfc.domain.sms.SmsReqBodyEntity;
import com.jccfc.iMessageTo.impl.ServerControlMessageTo;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Map;

public class HttpClientUtil {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    private static final String CHARSET = "UTF-8";

    private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sc = SSLContext.getInstance("TLSv1.2");
        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sc.init(null, new TrustManager[]{trustManager}, null);
        return sc;
    }

    /**
     * http的方式发送短信 2020年7月10日
     *
     * @param params
     * @param clazz
     * @param header
     */
    public static <W> W smsHttpPostSendJson(String url, SmsReqBodyEntity params, Class<W> clazz, Map<String, String> header) {
        CloseableHttpResponse httpResponse = null;
        try {
            if (params == null || params.getBody() == null || params.getSmsReqHeader() == null || params.getBody().isEmpty()) {
                logger.error("http短信发送请求失败， 短信SmsReqBodyEntity参数不能为空 ， 短信的消息体（Body）不能为空，短息的验证体（SmsReqHeader）不能为空！  ");
                return null;
            }
            //采用绕过验证的方式处理https请求
            SSLContext sslcontext = createIgnoreVerifySSL();
            //设置协议http和https对应的处理socket链接工厂的对象
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", new SSLConnectionSocketFactory(sslcontext))
                    .build();
            PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            HttpClients.custom().setConnectionManager(connManager);
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = null;
            String result = null;
            httpClient = HttpClients.createDefault();
            //设置超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectionRequestTimeout(300000)
                    .setConnectTimeout(300000)
                    .setSocketTimeout(300000)
                    .build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("charset", "utf8");
            HttpEntity httpEntity = null;
            if (header != null && !header.isEmpty()) {
                for (String key : header.keySet()) {
                    httpPost.setHeader(key, header.get(key));
                }
            }
            String paramJson = JSON.toJSONString(params);
            httpEntity = new StringEntity(paramJson, CHARSET);
            logger.info("[HTTP-POST]StringEntity封装完成");
            httpPost.setEntity(httpEntity);
            //执行请求操作，并拿到结果（同步阻塞）
            logger.info("[HTTP-POST]开始执行请求");
            try {
                httpResponse = httpClient.execute(httpPost);
                if (HttpStatus.SC_OK != httpResponse.getStatusLine().getStatusCode()) {
                    logger.error("response post error {}", httpResponse);
                }
                //获取结果实体
                HttpEntity entity = httpResponse.getEntity();
                if (entity != null) {
                    //按指定编码转换结果实体为String类型
                    result = EntityUtils.toString(entity, "UTF-8");
                }
                EntityUtils.consume(entity);
            } finally {
                //释放链接
                if (httpResponse != null) {
                    httpResponse.close();
                } else {
                    logger.error("http短信发送请求失败，httpResponse为空！");
                }
            }
            logger.info("[HTTP-POST]响应报文:{}", result);
            W w = JSON.parseObject(result, clazz);
            return w;
        } catch (Exception e) {
            logger.error("http短信发送请求失败：", e);
        }
        return null;
    }

    /**
     * @Auther: qym
     * @Description: 向服务监控系统发送消息
     * @Param:
     * @Return:
     * @Date: 2021/1/18 15:17
     */
    public static boolean doPostToSystem(String url, ServerControlMessageTo serverControlMessageTo) {
        //获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //创建Post请求
        HttpPost httpPost = new HttpPost(url);
        //设置post请求请求头
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        //将消息发送实例转换为json对象
        String jsonString = JSON.toJSONString(serverControlMessageTo);
        //构建消息发送的entity 编码默认utf-8
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        //post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        httpPost.setEntity(entity);
        // 响应模型
        CloseableHttpResponse response = null;
        try {
            //由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            //从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                System.out.println("响应内容长度为:" + responseEntity.getContentLength());
                String responseStr = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
                System.out.println("响应内容为:" + responseStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

}
